package org.yxing.palpalgps.activity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.yxing.palpalgps.AbstractActivity;
import org.yxing.palpalgps.PalPalGPSApplication;
import org.yxing.palpalgps.R;
import org.yxing.palpalgps.domain.AsyncImageLoader;
import org.yxing.palpalgps.domain.UserInfo;
import org.yxing.palpalgps.models.ChatMessageModel;
import org.yxing.palpalgps.provider.RecentChatsProvider;
import org.yxing.palpalgps.provider.RecentChatsProvider.RecentChats;
import org.yxing.palpalgps.services.XMPPService;
import org.yxing.palpalgps.utils.Helper;
import org.yxing.palpalgps.widget.AsyncImageView;

import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

public class ChatActivity extends AbstractActivity implements OnClickListener {
    
    private static final String TAG = "ChatActivity";
    
    private static final int HANDLE_MESSAGE_LISTENER = 0;
    
    private static final String URL_PROFILE_INFO = "profile/info";
    
    private Adapter mAdapter;
    
    private UserInfo user;
    
    private XMPPService mService;
    
    private String fuid;
    
    private String fname;
    
    private String fportrait;
    
    private String chatType;
    
    private Button sendButton;
    
    private EditText editMessage;
    
    private TextView nameView;
    
    private String empty = "";
    
    private Chat chat;
    
    private ListView mListView;
    
    /**
     * on create
     */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chat);
        setTitle(getString(R.string.chat));
        
        //get friend profile
        Intent intent = getIntent();
        fuid = intent.getStringExtra("fuid");
        fname = intent.getStringExtra("name");
        fportrait = intent.getStringExtra("portrait");
        chatType = intent.getStringExtra("type");
        if (chatType == null)
        	chatType = RecentChats.TYPE_CHAT;
        
        //get application
        PalPalGPSApplication application = (PalPalGPSApplication) getApplication();
        //get current user
        user = application.getUser();
        //create adapter
        mAdapter = new Adapter();
        sendButton = (Button) findViewById(R.id.sendButton);
        editMessage = (EditText) findViewById(R.id.editMessage);
        
        //set friend name
        nameView = (TextView) findViewById(R.id.nameView);
        nameView.setText(fname);
        
        //set friend portrait
        if (chatType != null && !chatType.equals(RecentChats.TYPT_GROUP)) {
            AsyncImageView faceView = (AsyncImageView) findViewById(R.id.faceView);
            faceView.setUrl(Helper.getSmallPictureUrl(fportrait));
//            mAsyncImageLoader.loadDrawable(Helper.getSmallPictureUrl(fportrait), faceView);
        }
        
        mListView = (ListView) findViewById(android.R.id.list);
        mListView.setAdapter(mAdapter);
        
        //send button click listener
        sendButton.setOnClickListener(this);
    }
    
    /**
     * on resume
     */
    public void onResume() {
        super.onResume();
        //bind service
        bindService(new Intent(this, XMPPService.class), mServiceConnection, BIND_AUTO_CREATE);
        loadProfile();
    }
    
    /**
     * on pause
     */
    public void onPause() {
        super.onPause();
        //clear message quantity
        ContentValues values = new ContentValues();
        values.put(RecentChats.QUANTITY, 0);
        String where = RecentChats.UID + "=? AND " + RecentChats.FUID + "=?";
        getContentResolver().update(RecentChatsProvider.CONTENT_URI, values, where, new String[]{user.getId(), fuid});
        //remove message listener
        chat.removeMessageListener(mMessageListener);
        //unbind service
        unbindService(mServiceConnection);
    }
    
    private class Adapter extends BaseAdapter {
        
        private ArrayList<ChatMessageModel> data;
        
        private SimpleDateFormat dateFormat;
        
        public Adapter() {
            data = new ArrayList<ChatMessageModel>();
            dateFormat = new SimpleDateFormat("HH:mm");
        }
        
        public int getCount() {
            return data.size();
        }

        public ChatMessageModel getItem(int arg0) {
            return data.get(arg0);
        }

        public long getItemId(int position) {
            return getItem(position).getId();
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            convertView = getLayoutInflater().inflate(R.layout.chat_message, null);
            TextView dateView = (TextView) convertView.findViewById(R.id.date);
            TextView fromView = (TextView) convertView.findViewById(R.id.fromView);
            TextView messageView = (TextView) convertView.findViewById(R.id.messageView);
            ChatMessageModel model = getItem(position);
            
            dateView.setText(dateFormat.format(model.getDate()));
            String fromName = (model.getFrom().equals(fuid)) ? fname : getString(R.string.me);
            fromView.setText(fromName);
            messageView.setText(model.getBody());
            return convertView;
        }
        
        public void add(ChatMessageModel model) {
            data.add(model);
            notifyDataSetChanged();
        }
        
        public void add(int index, ChatMessageModel model) {
        	data.add(index, model);
            notifyDataSetChanged();
        }
        
        public void clear() {
        	data.clear();
        }
    }
    
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.sendButton:
            sendMessage();
            break;
        }
    }
    
    /**
     * fetch data from database
     */
    private void fetchData() {
        Cursor c = mService.getChatDatabaseAdapter().fetchData(user.getId(), fuid);
        mAdapter.clear();
        while (c.moveToNext()) {
            ChatMessageModel model = new ChatMessageModel();
            model.setFrom(c.getString(1));
            model.setTo(c.getString(2));
            model.setEncodeBody(c.getString(3));
            model.setDate(new Date(c.getLong(4)));
            mAdapter.add(0, model);
        }
    }
    
    private void sendMessage() { 
        String msg = editMessage.getText().toString();
        if (msg.length() > 0) {
            ChatMessageModel model = new ChatMessageModel(user.getId(), fuid, msg);
            //add to adapter
            mAdapter.add(model);
            //add to database
            mService.insertChatMessageToDatabase(model);
            //send message to service
            try {
                if (chat != null) {
                    Log.v(TAG, "send message " + model.getBody());
                    chat.sendMessage(model.getEncodeBody());
                }
            } catch (XMPPException e) {
                Log.w(TAG, e.getMessage());
            }
            //clear edit input
            editMessage.setText(empty);
        }
    }
    
    /**
     * 
     */
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.v(TAG, "onServiceDisconnected");
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = ((XMPPService.MyBinder) service).getService();
            String toHost = chatType.equals(RecentChats.TYPT_GROUP) ? "broadcast." : "";
            chat = mService.getConn().getChatManager().createChat(fuid + "@" + toHost + Helper.getHost() + "/" + Helper.RESOURCE, mMessageListener);
            fetchData();
            Log.v(TAG, "create chat");
        }
    };
    
    private MessageListener mMessageListener = new MessageListener() {
        
        public void processMessage(Chat chat, Message message) {
            mHandler.sendMessage(mHandler.obtainMessage(HANDLE_MESSAGE_LISTENER, message));
        }
    };
    
    /**
     * handler
     */
    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            super.handleMessage(msg);
            if (msg.what == HANDLE_MESSAGE_LISTENER) {
                reseiveMessage((Message) msg.obj);
            }
        }
    };
    
    /**
     * 接收到消息后的处理方法
     * @param message 消息对象
     */
    private void reseiveMessage(Message message) {
        ChatMessageModel model = new ChatMessageModel();
        model.setFrom(XMPPService.subUid(message.getFrom()));
        model.setTo(XMPPService.subUid(message.getTo()));
        model.setEncodeBody(message.getBody());
        model.setDate(new Date());
        mAdapter.add(model);
    }
    
    /**
     * load profile
     */
    private void loadProfile() {
    }
}